package com.pan.download5.parse;

import com.pan.download5.parse.entity.auto2.Auto2InfoDirectory;
import com.pan.download5.parse.entity.auto2.Auto2InfoNext;
import com.pan.download5.parse.entity.auto2.Auto2InfoPage;
import com.pan.download5.parse.entity.auto2.Auto2InfoValue;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;

public class Auto2XmlParser {

    public Auto2XmlParser(String path) {
        URL xmlUrl = ClassLoader.getSystemResource(path);
        String fileUrl = xmlUrl.getFile();
        try {
            fileUrl = URLDecoder.decode(fileUrl, Charset.defaultCharset().name());
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(new File(fileUrl));
            parse(document);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (SAXException e) {
            throw new RuntimeException(e);
        }

    }


    private String website;
//    private String targetUrl;
    private Auto2InfoPage page;
    private Auto2InfoDirectory directory;

    public String getWebsite() {return website;}
//    public String getTargetUrl() {return targetUrl;}
    public Auto2InfoPage getPage() {return page;}
    public Auto2InfoDirectory getDirectory() {return directory;}

    private Element findElementByTagName(Element element, String tagName){
        NodeList nodeList = element.getElementsByTagName(tagName);
        if (nodeList.getLength() == 0){
            return null;
        }
        return (Element) nodeList.item(0);
    }
    private String findElementContentByTagName(Element element, String tagName){
        Element elementByTagName = findElementByTagName(element, tagName);
        if (elementByTagName == null) return null;
        else return elementByTagName.getTextContent().trim();
    }


    private NullPointerException createNullException(String tag){
        return new NullPointerException("Null Error: The "+tag+" of Auto2Crawler can not empty");
    }


    private Auto2InfoValue parseValue(Element valueElement){
        String xpathTagName = "xpath";
        String regexTagName = "regex";
        Auto2InfoValue resultValue = new Auto2InfoValue();
        String xpath = findElementContentByTagName(valueElement, xpathTagName);
        if (xpath == null){
            throw createNullException("value xpath");
        }
        resultValue.setXpath(xpath);
        String regex = findElementContentByTagName(valueElement, regexTagName);
        resultValue.setRegex(regex);
        return resultValue;
    }
    private Auto2InfoNext parseNext(Element nextElement){
        Auto2InfoValue value = parseValue(nextElement);
        Auto2InfoNext resultNext = new Auto2InfoNext();
        resultNext.setXpath(value.getXpath());
        resultNext.setRegex(value.getRegex());
        String conditionTagName = "condition";
        String clickTagName = "click";
        String condition = findElementContentByTagName(nextElement, conditionTagName);
        if (condition == null){
            throw createNullException("next>condition");
        }
        resultNext.setCondition(condition);
        String click = findElementContentByTagName(nextElement, clickTagName);
        resultNext.setClick(click);
        return resultNext;
    }


    private Auto2InfoDirectory parseDirectory(Element directoryElement){
        String titleTagName = "title";
        String chapNameTagName = "chap-name";
        String chapUrlTagName = "chap-url";
        String nextTagName = "next";

        Auto2InfoDirectory resultDirectory = new Auto2InfoDirectory();

        Element titleElement  = findElementByTagName(directoryElement, titleTagName);
        Element chapNameElement = findElementByTagName(directoryElement, chapNameTagName);
        Element chapUrlElement = findElementByTagName(directoryElement, chapUrlTagName);

        if (titleElement == null | chapUrlElement ==null| chapNameElement == null){
            throw createNullException("title or chap-name or chap-url");
        }
        Auto2InfoValue title = parseValue(titleElement);
        Auto2InfoValue chapName = parseValue(chapNameElement);
        Auto2InfoValue chapUrl = parseValue(chapUrlElement);
        resultDirectory.setTitle(title);
        resultDirectory.setChapName(chapName);
        resultDirectory.setChapUrl(chapUrl);

        Element nextElement = findElementByTagName(directoryElement, nextTagName);
        if (nextElement == null){
            resultDirectory.setNext(null);
        }else {
            Auto2InfoNext next = parseNext(nextElement);
            resultDirectory.setNext(next);
        }
        return resultDirectory;
    }

    private Auto2InfoPage parsePage(Element pageElement){
        String contentTagName = "content";
        String nextTagName = "next";

        Auto2InfoPage resultPage = new Auto2InfoPage();
        Element contentElement = findElementByTagName(pageElement, contentTagName);
        if (contentElement == null){
            throw createNullException(contentTagName);
        }
        Auto2InfoValue content = parseValue(contentElement);
        resultPage.setContent(content);

        Element nextElement = findElementByTagName(pageElement, nextTagName);
        if (nextElement == null){
            resultPage.setNext(null);
        }else {
            Auto2InfoNext next = parseNext(nextElement);
            resultPage.setNext(next);
        }
        return resultPage;
    }

    private void parse(Document document){
        document.normalizeDocument();
        Element rootElement = document.getDocumentElement();
        String configTagName = "config";
        Element configElement = findElementByTagName(rootElement, configTagName);
        if (configElement == null){
            throw createNullException("config");
        }
        String websiteTagName = "website";
        String targetTagName = "crawler-target";
        this.website = findElementContentByTagName(configElement, websiteTagName);
//        this.targetUrl = findElementContentByTagName(configElement, targetTagName);
//        if (this.website ==null || this.targetUrl == null){
//            throw createNullException("website or target");
//        }

        String directoryTagName = "directory";
        Element directoryElement = findElementByTagName(rootElement, directoryTagName);
        if (directoryElement == null){
            throw createNullException("directory");
        }
        this.directory = parseDirectory(directoryElement);


        String pageTagName = "page";
        Element pageElement = findElementByTagName(rootElement, pageTagName);
        if (pageElement == null){
            throw createNullException("page");
        }
        this.page = parsePage(pageElement);
    }


//    public static void main(String[] args) {
//        System.out.println(INSTANCE.getWebsite());
//        System.out.println(INSTANCE.getTargetUrl());
//        System.out.println(INSTANCE.getDirectory());
//        System.out.println(INSTANCE.getPage());
//    }



}
